package com.xayy.health.mgt.service.strategy.health;

import cn.kawins.base.result.CheckResult;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.spring.utils.SpringHolder;
import com.xayy.health.core.enums.ScoreRuleEnum;
import com.xayy.health.mgt.model.HealthAssessRecord;
import com.xayy.health.mgt.model.HealthAssessResult;
import com.xayy.health.mgt.model.vo.FractionIntervalScoreVo;
import com.xayy.health.mgt.model.vo.HealthAssessParam;
import com.xayy.health.mgt.model.vo.SatelliteNodeTreeVo;
import com.xayy.health.mgt.service.FractionIntervalScoreService;
import com.xayy.health.mgt.service.HealthAssessRecordService;
import com.xayy.health.mgt.service.HealthAssessResultService;
import com.xayy.health.mgt.service.impl.HealthAssessResultServiceImpl;
import com.xayy.health.mgt.service.strategy.AlgorithmStrategy;
import lombok.Builder;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Nie
 * @version V1.0
 * @date 2023/4/10 14:23
 */
@Builder

public class AnalyticHierarchyStrategy implements AlgorithmStrategy<HealthAssessParam> {

    private static FractionIntervalScoreService fractionIntervalScoreService;
    private static FractionIntervalScoreVo data;

    static {
        fractionIntervalScoreService = SpringHolder.getBean(FractionIntervalScoreService.class);

        data = fractionIntervalScoreService.selectByType(ScoreRuleEnum.HEALTH.getCode()).getData();
    }

    private CheckResult<Integer> assessment(SatelliteNodeTreeVo satelliteNodeTreeVo,
        Map<Long, HealthAssessResult> midScore, List<HealthAssessRecord> records) {
        Long mid = satelliteNodeTreeVo.getId();
        Integer sum = 0;
        HealthAssessResult result = midScore.get(mid);
        Integer aFloat = midScore.get(mid).getMultipleFraction();
        if (aFloat == null) {
            aFloat = 95;
            midScore.get(mid).setMultipleFraction(95);
        }

        // 手动打分则不去取下面节点的分值均值
        HealthAssessResult healthAssessResult = midScore.get(mid);
        List<SatelliteNodeTreeVo> children = satelliteNodeTreeVo.getChildren();
        if (1 == healthAssessResult.getScoringRule()) {
            sum = healthAssessResult.getMultipleFraction();
        } else {

            if (CollUtil.isNotEmpty(children)) {
                BigDecimal weightSum = BigDecimal.valueOf(0);
                for (SatelliteNodeTreeVo child : children) {
                    HealthAssessResult childResult = midScore.get(child.getId());

                    CheckResult<Integer> assessment = this.assessment(child, midScore, records);
                    if (assessment.no()) {
                        return CheckResult.fail(assessment.getCheckMsg());
                    }
                    sum += assessment.getData();

                    // 计算分系统的权重和
                    if (childResult != null) {
                        weightSum = weightSum.add(BigDecimal.valueOf(childResult.getEvaluatingWeight()));
                    }
                }
                // 判断权重和是不是等于1
                if (result.getEvaluatingWeight() != 0 && weightSum.doubleValue() != 1.0) {
                    return CheckResult.fail(satelliteNodeTreeVo.getName() + "：下的的子节点权重之和为" + weightSum + "，请确保权重为1");
                }
            }
            if (CollUtil.isEmpty(children)) {
                sum = aFloat;
            }
        }
        String satisfaction = ScoreRuleEnum.matchLevelStr(data.getIntervalList(), sum);
        healthAssessResult.setMultipleFraction(sum);
        healthAssessResult.setSatelliteName(satelliteNodeTreeVo.getNodeName());
        healthAssessResult.setIsComponent(CollUtil.isEmpty(children));
        healthAssessResult.setSatisfaction(satisfaction);
        HealthAssessRecord record = HealthAssessResultServiceImpl.buildRecord(healthAssessResult,
                satelliteNodeTreeVo.getNodeName(), satelliteNodeTreeVo.getName());
        records.add(record);
        midScore.get(mid).setFinishFraction(true);
        midScore.get(mid).setFractionTime(new Date());
        // 节点分值乘以权重，四舍五入取分值返回
        Double evaluatingWeight = healthAssessResult.getEvaluatingWeight();
        int round = (int) Math.round(sum * evaluatingWeight);
        return CheckResult.success(round);
    }

    /**
     * @param healthAssessParam 入参
     * @return CheckResult<?>
     * 计算根节点分数
     */
    @Override
    public CheckResult<?> process(HealthAssessParam healthAssessParam) {
        // 树
        List<SatelliteNodeTreeVo> list = healthAssessParam.getList();
        // 评估结果
        List<HealthAssessResult> assessResults = healthAssessParam.getAssessResults();
        String nodeName = null;
        Map<Long, HealthAssessResult> midScore =
                assessResults.stream().collect(Collectors.toMap(HealthAssessResult::getNodeMid, x -> x));
        List<HealthAssessRecord> records = new ArrayList<>(0);
        Integer sum = 0;
        // 树节点下第一层节点遍历
        if (CollUtil.isNotEmpty(list)) {
            BigDecimal weightSum = BigDecimal.valueOf(0);
            for (SatelliteNodeTreeVo satelliteNodeTreeVo : list) {
                HealthAssessResult result = midScore.get(satelliteNodeTreeVo.getId());

                CheckResult<Integer> assessment = assessment(satelliteNodeTreeVo, midScore, records);
                if (assessment.no()) {
                    return CheckResult.fail(assessment.getCheckMsg());
                }
                sum += assessment.getData();

                // 计算分系统的权重和
                if (result != null) {
                    weightSum = weightSum.add(BigDecimal.valueOf(result.getEvaluatingWeight()));
                }
            }
            // 判断权重和是不是等于1
            if (weightSum.doubleValue() != 1.0) {
                return CheckResult
                        .fail(healthAssessParam.getSatelliteName() + "：下的的分系统节点权重之和为" + weightSum + "，请确保权重为1");
            }
            nodeName = list.get(0).getNodeName();
        }
        String satisfaction = ScoreRuleEnum.matchLevelStr(data.getIntervalList(), sum);
        HealthAssessResult healthAssessResult = midScore.get(healthAssessParam.getMid());
        healthAssessResult.setMultipleFraction(sum);
        healthAssessResult.setSatelliteName(healthAssessParam.getSatelliteName());
        healthAssessResult.setIsComponent(false);
        healthAssessResult.setFinishFraction(true);
        healthAssessResult.setFractionTime(new Date());
        healthAssessResult.setAutoScore(true);
        healthAssessResult.setScoringRule(2);
        healthAssessResult.setSatisfaction(satisfaction);
        HealthAssessRecord record =
                HealthAssessResultServiceImpl.buildRecord(midScore.get(healthAssessParam.getMid()), nodeName, nodeName);
        records.add(record);
        HealthAssessResultService resultService = SpringHolder.getBean(HealthAssessResultService.class);
        resultService.updateListById(midScore.values());
        HealthAssessRecordService recordService = SpringHolder.getBean(HealthAssessRecordService.class);
        recordService.insertList(records);
        return CheckResult.success();
    }

}
